#include "Demo3d.h"

#include "Macros.h"

#include "Engine3d/Vector2.h"
#include "Engine3d/Color.h"

#include "Engine3d/Matrix4.h"
#include "Engine3d/Math.h"

#include "Engine3d/Geometry.h"

#include "Engine3d/Profiler.h"

#include <time.h>

using namespace Iride;

Demo3d::Demo3d(IGraphics* pGraphics, IInput* pInput):
 Game(pGraphics,pInput), mpUpdateFnc(&Demo3d::DullUpdate), mEngine3d(pGraphics),
 mVertices(NULL), mIndices(NULL), mColors(NULL)
{

}

Demo3d::~Demo3d()
{
	if (mVertices!= NULL) delete [] mVertices;
	if (mIndices!= NULL) delete [] mIndices;
	if (mColors!= NULL) delete [] mColors;
}


bool Demo3d::Init()
{
	Profiler::sPrintEnabled = true;


	Real left = -2.0f;
	Real right = 2.0f;
	Real bottom = -1.5f;
	Real top = 1.5f;
	Real near = 1.0f;
	Real far = 10.0f;

	mEngine3d.SetFrustum(left, right, bottom, top, near, far);

	SetCubeDemo();
	//SetSingleTriangleDemo();

	//mEngine3d.mWireFrame = true;

	mEngine3d.mWinding = WIND_CCW;

	return super::Init();
}


void Demo3d::DullUpdate()
{
}

void Demo3d::SetSingleTriangleDemo()
{
	mStartZ = -10.0f;

	Vector3 pointA = Vector3(-1.0f, -1.0f, mStartZ);
	Vector3 pointB = Vector3(0.0f, 1.0f, mStartZ);
	Vector3 pointC = Vector3(1.0f, -1.0f, mStartZ);

	Color colorA = Color(1.0f, 0.0f, 0.0f);
	Color colorB = Color(0.0f, 1.0f, 0.0f);
	Color colorC = Color(0.0f, 0.0f, 1.0f);

	mNumTriangles = 1;
	mNumVertices = 3;

	mVertices = new Vector3[mNumVertices];
	mIndices = new Uint[mNumTriangles * 3];
	mColors = new Color[mNumVertices];

	mVertices[0] = pointA;
	mVertices[1] = pointB;
	mVertices[2] = pointC;

	mIndices[0] = 0;
	mIndices[1] = 1;
	mIndices[2] = 2;

	mColors[0] = colorA;
	mColors[1] = colorB;
	mColors[2] = colorC;

	mpUpdateFnc = &Demo3d::SingleTriangleDemoUpdate;
}

void Demo3d::SingleTriangleDemoUpdate()
{
}

void Demo3d::SetCubeDemo()
{
	Color colorA = Color(1.0f, 0.0f, 0.0f);
	Color colorB = Color(0.0f, 1.0f, 0.0f);
	Color colorC = Color(0.0f, 0.0f, 1.0f);

	mNumTriangles = 12;
	mNumVertices = 8;

	mCounter = 0.0f;

	mVertices = new Vector3[mNumVertices];
	mIndices = new Uint[mNumTriangles * 3];
	mColors = new Color[mNumVertices];

	Math::RandSeed(23);

	for(Uint i = 0; i < mNumVertices; i++)
	{
		switch(i % 3)
		{
			case 0:
				mColors[i] = colorA;
				break;
			case 1:
				mColors[i] = colorB;
				break;
			case 2:
				mColors[i] = colorC;
				break;
		}
	}

	Geometry::cube(2.0f, mVertices, mIndices);
	for (Uint i = 0; i < 8; i++)
	{
		mVertices[i].z -= 3.0;
	}

	mpUpdateFnc = &Demo3d::CubeDemoUpdate;
}

void Demo3d::CubeDemoUpdate()
{
	mCounter += 0.01;
	if (mCounter > Math::PI)
	{
		mCounter = - Math::PI;
	}

	// mCounter = Math::PI / 4;

	Real zVal = -3.0;

	Geometry::cube(2.0f, mVertices, mIndices);
	for (Uint i = 0; i < 8; i++)
	{
		mVertices[i].z += zVal;
	}

	Matrix4 trCenter, rotX, rotY, trBack, final;

	trCenter.MakeTranslate(Vector4(0,0, - zVal,0));
	rotY.MakeRotateY(mCounter);
	rotX.MakeRotateX(mCounter);
	trBack.MakeTranslate(Vector4(0,0, zVal,0));

	final = trBack * rotY * rotX * trCenter;

	Vector4 vec4;

	for(Uint i = 0; i < mNumVertices; i++)
	{
		mVertices[i] = final *  mVertices[i];
	}
}


void Demo3d::Render()
{
	//mEngine3d.Draw(mPointA, mPointB, mPointC, mColorA, mColorB, mColorC);

	mEngine3d.BeginRender();

	Profiler profiler;

	profiler.resetTimer();
	mEngine3d.Draw(mVertices, mIndices, mColors, mNumTriangles);
	super::Render();
	#ifdef PROFILE_FRAME_RENDERING
	profiler.printElapsedMs("Demo3D rendered a frame in Ms: ");
	#endif

}

void Demo3d::Update()
{
	CALL_MEMBER_FN(*this,mpUpdateFnc)();

    super::Update();
}

bool Demo3d::HandleInput()
{
   return super::HandleInput();
}

void Demo3d::CleanUp()
{
	super::CleanUp();
}
